#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include "queue.h"

#define CREATE_SQL_NUM 100

// Size of the shared queue buffer
// Must be greater than zero
const int buffer_size = 100;
// Number of producer threads to start
// Must be greater than zero
const int producers = 16;
// Number of integers to be produced by each producer thread
// Must be greater than zero
const int producer_amount = 10;
// Number of consumer threads to start
// Must be greater than zero
const int consumers = 1;
// producers * producer_amount / consumers must be a whole integer

char sample[] = {
    48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
    65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
    97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122
};

int rand_x(unsigned int *nextp)
{
    *nextp = *nextp * 1103515245 + 12345;
    return (unsigned int)(*nextp / 65536) % 32768;
}

char* createSQL() {
    unsigned int seed  = time(NULL)^pthread_self(); 

    int dataLength = (11 + 20 + 50 + 100 + 200 + 300 + 400 + 7) * CREATE_SQL_NUM;
    char* pSqls = (char *)malloc(dataLength);

    int vars[][3] = {
         {0, 0, 0},
         {1, 0, 20},
         {1, 0, 50},
         {1, 0, 100},
         {1, 0, 200},
         {1, 0, 300},
         {1, 0, 400}
    };

    int curLen = 0;
    int intStrLen = 0;

    int i = 0;
    for (; i<CREATE_SQL_NUM; i++) {
        int j = 0;
        for (; j < 7; j++) {
            if (vars[j][0] == 0) {
                int value = (rand_x(&seed) << 17) | (rand_x(&seed) << 2) | (rand_x(&seed) & 0x03);
                int n = sprintf(pSqls + curLen, "%d", value);
                curLen += n;
            } else {
                int randStrLen = rand_x(&seed) % vars[j][2];
                int i;
                for (i=0; i<randStrLen; i++) {
                    int pos = rand_x(&seed) % 62;
                    pSqls[curLen] = sample[pos];
                    curLen++;
                }
            }
            if (j != 6) {
                pSqls[curLen] = '|';
                curLen++;
            }
        }
        pSqls[curLen] = '\n';
        curLen++;
    }
    curLen++;
    pSqls[curLen] = '\0';
    return pSqls;
}



void *producer(void *arg) {
    int loopTimes = 50000000 / producers / CREATE_SQL_NUM;
    int i = 0;
    for (; i<loopTimes; i++) {
        char *pSql = createSQL();
        queue_enqueue(arg, pSql);
    }
}

void *consumer(void *arg) {
    FILE * fp;
    fp = fopen ("C:\\Users\\49491\\c.txt", "w");
    static char buff[1024 * 1024 * 10];
    setvbuf(fp, buff, _IOFBF, 1024 * 1024 * 10);

    int loopTimes = 50000000 / CREATE_SQL_NUM;
    char* pSQL = NULL;
    int i = 0;
    while (1) {
        char* pSql = (char*)malloc(5500);
        memset(pSql, 65, 5500);
        fputs(pSql, fp);
        free(pSql);

        i++;
        if (i == loopTimes)
            break;
    }
    fclose(fp);
}

void testIO() {
    // FILE * fp;
    // fp = fopen ("C:\\Users\\49491\\c.txt", "w");
    // static char buff[1024 * 1024 * 10];
    // setvbuf(fp, buff, _IOFBF, 1024 * 1024 * 10);

    // int loopTimes = 50000000 / CREATE_SQL_NUM;
    // char* pSQL = NULL;
    // int i = 0;
    // while (1) {
    //     char* pSql = createSQL();
    //     fputs(pSql, fp);
    //     free(pSql);

    //     i++;
    //     if (i == loopTimes)
    //         break;
    // }
    // fclose(fp);

    FILE *fp;
    fp = fopen ("C:\\Users\\49491\\h.txt", "w");
    int i = 0;
    char pStr[1024 * 1024];
    memset(pStr, 65, 1024 * 1024);
    // for (; i<100000000; i++)
    // {
    //     fputs("abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij\n",fp);
    //     // fwrite("abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij\n",1,51, fp);
    // }
    for (; i<1024; i++) {
        fputs(pStr, fp);
    }
    fclose(fp);
}

int main(void) {
    time_t start,stop;
    start = time(NULL);

    void *buffer[buffer_size];
    QUEUE_INITIALIZER(queue,buffer);
    
    int i;
    pthread_t producers[producers];
    for (i = 0; i < sizeof(producers) / sizeof(producers[0]); ++ i)
    {
            pthread_create(&producers[i], NULL, producer, &queue);
    }
    pthread_t consumers[consumers];
    for (i = 0; i < sizeof(consumers) / sizeof(consumers[0]); ++ i)
    {
            pthread_create(&consumers[i], NULL, consumer, &queue);
    }
    for (i = 0; i < sizeof(producers) / sizeof(producers[0]); ++ i)
    {
            pthread_join(producers[i], NULL);
    }
    for (i = 0; i < sizeof(consumers) / sizeof(consumers[0]); ++ i)
    {
            pthread_join(consumers[i], NULL);
    }
    
    queue_destroy(&queue);

    // testIO();
    

    stop = time(NULL);
    printf("Use Time:%ld\n",(stop-start));
    return 0;
}

